
package util;
import java.io.*;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import socketEnv.DataUtil;
import java.io.IOException;
import java.net.InetAddress;

public class FtpUtil {

    private static FTPClient ftp;
    private static String remoteInetAddr = "192.168.15.249";//需要连接的IP地址
    public static Ftp ftp249 = new Ftp("192.168.15.249", "admin", "map");

    /**
     * 传入需要连接的IP，返回是否连接成功
     * @param remoteAddr
     * @return
     */
    public static boolean isReachable(String remoteAddr) {
        boolean reachable = false;
        try {
            InetAddress address = InetAddress.getByName(remoteAddr);
            reachable = address.isReachable(5000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return reachable;
    }

    /**
     * 获取ftp连接
     *
     * @return
     * @throws Exception
     */
    public static boolean connectFtp() throws Exception {
        if(!isReachable(remoteInetAddr)){
            Runtime.getRuntime().exec("route delete  192.168.15.249  mask 255.255.255.255 192.168.15.1");
            Runtime.getRuntime().exec("route -p add  192.168.15.249  mask 255.255.255.255 192.168.15.1");
        }
        if(!isReachable(remoteInetAddr)){
            throw new Exception("ipAddr inaccessible");
        }
        ftp = new FTPClient();
        boolean flag = false;
        int reply;
        try {
            if (ftp249.getPort() == null) {
                ftp.connect(ftp249.getIpAddr(), 21);
            } else {
                ftp.connect(ftp249.getIpAddr(), ftp249.getPort());
            }
            ftp.login(ftp249.getUserName(), ftp249.getPwd());
        } catch (IOException e) {
            e.printStackTrace();
        }
        ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
        ftp.setControlEncoding("UTF-8");
        reply = ftp.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {
            ftp.disconnect();
            return flag;
        }
        ftp.changeWorkingDirectory(ftp249.getPath());
        flag = true;
        // Info.out("ftp sever connected:" + ftp249.getIpAddr());
        return flag;
    }

    /**
     * 关闭ftp连接
     */
    public static void closeFtp() {
        if (ftp != null && ftp.isConnected()) {
            try {
                ftp.logout();
                ftp.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @param remoteWorkingDir  TestMap  目录必须存在
     * @param loclaFilePath    TestMap/testRangeTheme.png  是文件则上传该文件，是目录则上传该目录及其下所有内容（文件、文件夹）
     * @throws Exception
     */
    public static void uploadFile(String remoteWorkingDir, String loclaFilePath) throws Exception {
        if (ftp == null || ftp.isConnected() == false) {
            connectFtp();
        }
        ftp.changeWorkingDirectory(DataUtil.expectPicturePath + remoteWorkingDir);
        File file = new File(DataUtil.resultPicturePath + loclaFilePath);
        if (!file.exists()) {
            throw new Exception("local file not exists");
        }
        uploadFile(file);
    }

    /**
     * ftp上传文件/文件夹
     * @param f
     * @throws Exception
     */
    public static void uploadFile(File f) throws Exception {
        if (f.isDirectory()) {
            ftp.makeDirectory(f.getName());//文件夹存在时，不执行这一步，文件夹不存在时，执行这一步创建文件夹。
            //Info.out("makeDirectory:" + f.getName());
            ftp.changeWorkingDirectory(f.getName());
            File[] files = f.listFiles();
            for (File file : files) {
                if (file.isDirectory()) {
                    uploadFile(file);
                    ftp.changeToParentDirectory();
                } else {
                    ftp.enterLocalPassiveMode();
                    FileInputStream input = new FileInputStream(file);
                    //Info.out("ready to upload file:" + file.getName());
                    ftp.storeFile(file.getName(), input);//强制覆盖已有文件
                    input.close();
                    // Info.out("file uploaded:" + file.getName());
                }
            }
        } else {
            ftp.enterLocalPassiveMode();
            FileInputStream input = new FileInputStream(f);
            ftp.storeFile(f.getName(), input);
            input.close();
        }
    }

    /**
     * Download a single file from the FTP server
     * @param ftpClient      an instance of org.apache.commons.net.ftp.FTPClient class.
     * @param remoteFilePath path of the file on the server.
     * @param savePath       path of directory where the file will be stored.
     * @return true if the file was downloaded successfully, false otherwise
     * @throws IOException if any network or IO error occurred.
     */
    public static boolean downloadSingleFile(FTPClient ftpClient, String remoteFilePath, String savePath) throws Exception {
        File saveDir = new File(savePath+"/");
        //创建多级目录
        if(!saveDir.exists()){
            saveDir.mkdirs();
            if(!saveDir.exists()) {
                Info.out("目录创建失败!");
            }
        }
        File reomteFile = new File(remoteFilePath);
        File saveFile = new File(savePath +"/"+ reomteFile.getName());
        if(saveFile.exists()){
            saveFile.delete();
        }
        ftp.enterLocalPassiveMode();
        FileOutputStream outputStream = new FileOutputStream(saveFile);
        try {
            //return ftpClient.retrieveFile(new String(remoteFilePath.getBytes("GB2312"),"ISO-8859-1"), outputStream);
            return ftpClient.retrieveFile(remoteFilePath, outputStream);
        } catch (IOException ex) {
            throw ex;
        } finally {
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
        }
    }

    /**
     * Download a whole directory from a FTP server.
     * @param ftpClient  an instance of org.apache.commons.net.ftp.FTPClient class.
     * @param remoteDir  Path of the parent directory of the current directory being
     *                   downloaded.
     * @param saveDir    path of directory where the whole remote directory will be
     *                   downloaded and saved.
     * @throws IOException if any network or IO error occurred.
     */
    public static void downloadDirectory(FTPClient ftpClient, String remoteDir, String saveDir) throws Exception {
        ftp.enterLocalPassiveMode();
        FTPFile[] subFiles = ftpClient.listFiles(remoteDir);
        for(int i = 2;i < subFiles.length;i++){
            String currentFileName = subFiles[i].getName();
            String filePath = remoteDir + "/" + currentFileName;
            String newDirPath = saveDir+"/"+ currentFileName;
            if (subFiles[i].isDirectory()) {
                File newDir = new File(newDirPath);
                boolean created = newDir.mkdirs();
                if (created) {
                    System.out.println("CREATED the directory: " + newDirPath);
                } else {
                    System.out.println("COULD NOT create the directory: " + newDirPath);
                }
                // download the sub directory
                downloadDirectory(ftpClient, filePath, saveDir);
            } else {
                // download the file
                boolean success = downloadSingleFile(ftpClient, filePath,new File(newDirPath).getParent());
                if (success) {
                    System.out.println("DOWNLOADED the file: " + filePath);
                } else {
                    System.out.println("COULD NOT download the file: " + filePath);
                }
            }

        }
    }

    /**
     * remotePath 可以是文件或者目录，会按照ftp完整目录下载。
     * @param remotePath   示例：TestMap/testRangeTheme.png，TestMap
     * @param destinationDir  示例：如G:/test
     * @throws Exception
     */
    public static void downLoad(String remotePath, String destinationDir) throws Exception {
        if (ftp == null || ftp.isConnected() == false) {
            connectFtp();
        }
        try {
            File file = new File(DataUtil.remoteDataPath+remotePath);
            String fileName = file.getName();
            boolean isFile = true;
            if (fileName.lastIndexOf('.') == -1) {
                isFile = false;
            }
            if (isFile) {
                FtpUtil.downloadSingleFile(ftp, DataUtil.remoteDataPath+remotePath,DataUtil.localDataPath+destinationDir);
            } else {
                FtpUtil.downloadDirectory(ftp, DataUtil.remoteDataPath+remotePath, DataUtil.localDataPath+destinationDir);
            }
            if (!new File(DataUtil.localDataPath+destinationDir).exists()) {
                throw new Exception("File still not exist,download fail");
            }
            System.out.println("downLoad OK");
        } finally {
            closeFtp();
        }
    }

    /**
     *下载多个文件，到目标位置
     * @param remotePath 如：{"/GUIData/900/SampleData/City/Changchun.udb","/GUIData/900/SampleData/City/Changchun.udd"}
     * @param destinationDir 如：../GUIData/900/SampleData/City,和源代码、测试代码同级
     * @throws Exception
     */
    public static void DownloadFiles(String[] remotePath, String destinationDir) throws Exception {
        if (ftp == null || ftp.isConnected() == false) {
            connectFtp();
        }
        for (String filePath:remotePath) {
            FtpUtil.downloadSingleFile(ftp, filePath, destinationDir);
        }
        closeFtp();
    }

    /**
     * 下载文件：测试数据在FTP和本地目录结构一致
     * @param destinationPath "E:\\ideaWorkspcae\\CrossTest\\SuperMap-iDesktop-Cross/./GUIData/SampleData/City/Changchun.udd"
     * @return destinationPath
     * @throws Exception
     */
    public static String downLoadFile(String destinationPath) throws Exception {
        String remotePath = destinationPath.substring(destinationPath.lastIndexOf("/GUIData"));
        downLoad(remotePath, destinationPath);
        return destinationPath;
    }

    /**
     * 下载目录：测试数据在FTP和本地目录结构一致
     *
     * @param destinationPath "E:\\ideaWorkspcae\\CrossTest\\SuperMap-iDesktop-Cross/./GUIData/SampleData/City/"
     * @return destinationPath
     * @throws Exception
     */
    public static String downLoadDir(String destinationPath) throws Exception {
        String remotePath = destinationPath.substring(destinationPath.lastIndexOf("/GUIData"));
        //下载目录的方法中会按照remotePath在本地新建同样的目录结构，所以savePath指定到根目录即可
        String savePath = destinationPath.substring(0,destinationPath.lastIndexOf("/GUIData")-1);
        downLoad(remotePath, savePath);
        return destinationPath;
    }

    /**
     * 下载UDB，自动下载UDD,路径与远程路径一致。认为数据源UDD和UDB大小写一致。
     *
     * @return
     */
    public static String downLoadUDB(String destinationPath) throws Exception {
        String remotePath = destinationPath.substring(destinationPath.lastIndexOf("/GUIData"));
        downLoadFile(destinationPath);
        String extensionName = destinationPath.substring(destinationPath.lastIndexOf("."), destinationPath.length());
        String theOtherExtensionName = null;
        switch (extensionName) {
            case ".udb":
                theOtherExtensionName = ".udd";
                break;
            case ".udd":
                theOtherExtensionName = ".udb";
                break;
            case ".UDB":
                theOtherExtensionName = ".UDD";
                break;
            case ".UDD":
                theOtherExtensionName = ".UDB";
                break;
            default:
                break;
        }
        destinationPath = destinationPath.replaceAll(extensionName, theOtherExtensionName);
        downLoadFile(destinationPath);
        return destinationPath;
    }


    /**
     * 调试上传下载功能
     */
    public static void main(String[] args) throws Exception {
        //uploadFile("TestMap","TestMap/testRangeTheme.png");//上传单个文件,ftp上必须存在TestMap文件夹
        //uploadFile("","TestMap");//上传TestMap目录及其下的所有文件到expectPicturePath目录中
        //downLoad("SampleData/City/Changchun.udb","SampleData/City");//下载指定文件到指定目录
        downLoad("SampleData/City","tt");//下载指定目录下的所有内容到指定目录
    }

}
